﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.ServiceModel;
using System.Configuration;
using PServiceBus.Core.Runtime;
using System.ServiceModel.Description;
using System.Threading;
using PServiceBus.Services.Gateway.Runtime;
using PServiceBus.Services.Gateway.Services;
using System.Xml;
using Phoenix.ReflectionExtensions;
using PServiceBus.Gateway.Interfaces;
using PServiceBus.Core.Runtime.Configuration;

namespace PServiceBus.Endpoints.Router {
	public partial class Service : ServiceBase {
		private static int _routerPort;
		private RouterService _service;
		private static string _routerName;
        private static string _messageBusType;

		public Service() {
			InitializeComponent();
			ServiceName = _routerName;
		}

		protected override void OnStart(string[] args) {
            DynamicBroker.Broker[_messageBusType].New();
			CloseService();
			Configure();
			var address = String.Format("endpoint://*:{0}", _routerPort);
			_service = new RouterService(address);
		}

		protected void Configure() {
			PServiceBus.Core.Runtime.SerializationBootstrapper.Configure();
			PServiceBus.Services.Gateway.Runtime.SerializationBootstrapper.Configure();
		}

		protected override void OnStop() {
			CloseService();
		}

		private void CloseService() {
			if (_service != null) _service.Dispose();
			_service = null;
		}

		static void LoadServiceInfo(string id) {
            var service = ConfigurationParser.Process("services.xml")
                    .Select(x => x["service"] as Dictionary<string, object>)
                    .Select(x => x.ToDictionary(kv => kv.Key, kv => kv.Value == null ? string.Empty : kv.Value.ToString()))
                    .First(x => x["id"] == id);

			_routerName = service["name"];
			_routerPort = Convert.ToInt32(service["port"]);
            _messageBusType = service["messageBusType"];
			ShellHelper.NetShAddTCPFirewall(_routerName, _routerPort);
		}

		static void Main(string[] args) {
			if (args.Length < 1)
				throw new ArgumentException("Router Service Require service name to be passed to the command line");
			LoadServiceInfo(String.Join(" ", args));
			ServiceBase[] ServicesToRun;
			ServicesToRun = new ServiceBase[] 
			{ 
				new Service() 
			};
			ServiceBase.Run(ServicesToRun);
		}
	}
}
